package com.haiqiu.tools.excel.utils;

import com.haiqiu.tools.common.utils.HttpServletUtils;
import org.apache.commons.jexl3.JexlBuilder;
import org.jxls.common.Context;
import org.jxls.expression.JexlExpressionEvaluator;
import org.jxls.transform.Transformer;
import org.jxls.util.JxlsHelper;
import org.springframework.core.io.ClassPathResource;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

/**
 * @author HaiQiu
 * @since 2023/3/8
 * JXLS填充式导出excel文件列表数据
 */
public class ExcelJxlsUtils {

    public static final String XLSX = ".xlsx";

    
    public static void exportExcel(InputStream is, OutputStream os, Map<String, Object> model) throws IOException {
        Context context = new Context();
        if (model != null) {
            for (String key : model.keySet()) {
                context.putVar(key, model.get(key));
            }
        }
        JxlsHelper jxlsHelper = JxlsHelper.getInstance();
        Transformer transformer = jxlsHelper.createTransformer(is, os);
        JexlExpressionEvaluator evaluator = (JexlExpressionEvaluator) transformer.getTransformationConfig()
                .getExpressionEvaluator();
        Map<String, Object> funcs = new HashMap<String, Object>();
        funcs.put("utils", new ExcelJxlsUtils()); // 添加自定义功能
        evaluator.setJexlEngine(new JexlBuilder().namespaces(funcs).create());
        jxlsHelper.processTemplate(context, transformer);
    }

    public static InputStream getTemplate(String filePath) {
        ClassPathResource classPathResource = new ClassPathResource(filePath);
        try {
            return classPathResource.getInputStream();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void exportExcel(InputStream is, Map<String, Object> model) throws IOException {
        long millis = System.currentTimeMillis();
        String fileName = millis + ".xlsx";
        OutputStream outputStream = Files.newOutputStream(Paths.get(fileName));
        exportExcel(is, outputStream, model);
        File file = new File(fileName);
        byte[] bytes = getBytesFromFile(file);
        export(fileName, bytes, HttpServletUtils.getServletResponse());
    }

    public static void exportExcel(InputStream is, String fileName, Map<String, Object> model) throws IOException {
        if (!fileName.endsWith(XLSX)) {
            fileName = fileName + XLSX;
        }
        OutputStream outputStream = Files.newOutputStream(Paths.get(fileName));
        exportExcel(is, outputStream, model);
        File file = new File(fileName);
        byte[] bytes = getBytesFromFile(file);
        export(fileName, bytes, HttpServletUtils.getServletResponse());
    }

    /**
     * <p>Description: 文件类型转换为byte</p>
     *
     * @param file 文件
     * @return byte
     */
    public static byte[] getBytesFromFile(File file) {
        if (file == null) {
            return null;
        }
        FileInputStream stream = null;
        ByteArrayOutputStream out = null;
        try {
            stream = new FileInputStream(file);
            out = new ByteArrayOutputStream(1000);
            byte[] b = new byte[1000];
            int n;
            while ((n = stream.read(b)) != -1) {
                out.write(b, 0, n);

            }
            return out.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (stream != null) {
                    stream.close();
                }
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            file.delete();
        }
        return null;
    }


    private static void export(String fileName, byte[] bytes, HttpServletResponse response) {
        try (OutputStream ouputStream = response.getOutputStream()) {
            // 设置输出的格式
            String name = URLEncoder.encode(fileName, "UTF-8");
            //自定义的header
            response.setHeader("requestType", "file");
            // 自定义的header
            response.setHeader("requestFileName", name);
            //设置这个header 可见
            response.setHeader("Access-Control-Expose-Headers", "requestType,requestFileName");

            //设置响应类型为html，编码为utf-8，处理相应页面文本显示的乱码
            response.setContentType("application/octet-stream;charset=UTF-8");
            //设置文件头：最后一个参数是设置下载文件名
            response.setHeader("Content-disposition", "attachment;fileName=" + name);
            ouputStream.write(bytes);
            ouputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static byte[] toByteArray(InputStream input) throws IOException {

        ByteArrayOutputStream output = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024 * 4];
        int n = 0;
        while (-1 != (n = input.read(buffer))) {

            output.write(buffer, 0, n);
        }
        return output.toByteArray();
    }
}
